Spring 使用简单Demo进行源码调试(三)

版权声明:本文为博主原创文章,转载请注明出处,谢谢!

版权声明:本文为博主原创文章,转载请注明出处:http://blog.jerkybible.com/2015/05/11/Spring 使用简单Demo进行源码调试(三)/

访问原文「Spring 使用简单Demo进行源码调试(三)

接上篇日志Spring 使用简单Demo进行源码调试(二)继续。

上篇提到了主要的初始化函数refresh,函数源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 为了刷新准备上下文
prepareRefresh();
// 利用子类完成内部bean factory的刷新
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 使用本地上下文准备bean factory
prepareBeanFactory(beanFactory);
try {
// 允许在上下文子类中完成bean factory后处理
postProcessBeanFactory(beanFactory);
// 调用上下文注册的bean factory处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 注册拦截bean创建的bean处理器
registerBeanPostProcessors(beanFactory);
// 初始化上下文中消息源
initMessageSource();
// 初始化上下文中的事件多播
initApplicationEventMulticaster();
// 在特定上下文子类中初始化其他特殊bean
onRefresh();
// 检查监听器bean并注册
registerListeners();
// 实例化所有剩余(non-lazy-init)单例
finishBeanFactoryInitialization(beanFactory);
// 发布相应的事件
finishRefresh();
}
catch (BeansException ex) {
logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}

先把prepareRefresh的代码贴出来。这段代码主要功能是初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* Prepare this context for refreshing, setting its startup date and
* active flag as well as performing any initialization of property sources.
*/
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
synchronized (this.activeMonitor) {
this.active = true;
}
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// Initialize any placeholder property sources in the context environment
initPropertySources();
// Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
}

这块基本是数据准备功能, 目前这一块没有实际用到。
接着我们看比较重要的一步

1
2
// 利用子类完成内部bean factory的刷新
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

先展开obtainFreshBeanFactory函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* Tell the subclass to refresh the internal bean factory.
* 使用子类完成内部bean factory
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}

我们主要看refreshBeanFactory()这一步,分为以下步骤:
1. 如果有bean factory,删除之;
2. 新建一个bean factory;
3. 设置一个序列化Id;
4. 使用的上下文自定义内部bean factory;
5. 加载bean 定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* This implementation performs an actual refresh of this context's underlying
* bean factory, shutting down the previous bean factory (if any) and
* initializing a fresh bean factory for the next phase of the context's lifecycle.
*/
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}

现在看一下第5步,加载bean定义,其实现如下。可以看到,这一步将beanFactory传入XmlBeanDefinitionReader的构造函数,新建一个XmlBeanDefinitionReader对象,然后对其环境进行设置。其中Environment表示当前应用程序运行的环境接口;ResourceLoader表示加载资源策略接口;EntityResolver表示实体解析接口。最后初始化XmlBeanDefinitionReader对象,然后使用这个对象加载bean 定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* Loads the bean definitions via an XmlBeanDefinitionReader.
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
* @see #initBeanDefinitionReader
* @see #loadBeanDefinitions
*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}

再看下一步,这个方法比较好理解,就是使用已有的配置资源或者配置文件进行加载,当前没有配置资源,所以只使用配置文件进行加载。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 使用XmlBeanDefinitionReader实例加载bean定义
* @param reader the XmlBeanDefinitionReader to use
*/
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}

来看reader.loadBeanDefinitions(configLocations);这一步。这一步看起来很复杂,但最主要的还是loadBeanDefinitions(resources)这一步。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**
* 使用配置文件加载bean定义
*/
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
int loadCount = loadBeanDefinitions(resources);
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// Can only load single resources by absolute URL.
Resource resource = resourceLoader.getResource(location);
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
}
}

下一回展开loadBeanDefinitions(resources)。

Jerky Lu wechat
欢迎加入微信公众号